# -*- coding: utf-8 -*-
import requests, time, datetime
import constant
import os
import uuid
import oss2
import json
from urllib import request
from bot_log import BotLogger

logger = BotLogger(os.path.basename(__file__)).getLogger()


def handle_error(res, normal_status_code):
    """
    统一处理workai平台返回的error
    :param res: 调用接口的返回
    :param normal_status_code: 正常返回的status code
    :return: 返回错误信息
    """
    if res is None or res.status_code == normal_status_code:
        return ''

    logger.info('The res is %s' % res)
    err = 'Unknown errors'
    try:
        if 'message' in res.json():
            err = res.json()['message']
    except:
        pass

    return err

#  密码方式获取access_token
def get_token_by_password(username, password, tenant_id):
    """

    :param username: 系统管理员用户
    :param password: 系统管理员密码
    :param tenant_id: 客户在workai云平台唯一表示
    :return: 返回access_token, refresh_token 以及error, access_token用于访问接口的令牌, refresh_token
    用于刷新获取新的access_token, error为返回的错误信息
    """
    data = {
        'grant_type': 'password',
        'username': username,
        'password': password,
        'scope': 'global_access:tenant_admin,tenant:%s' % tenant_id,
    }
    path = '%s/uaa/v1/auth/tokens' % constant.WACLOUD_API_ENDPOINT    #
    res = requests.post(path, json=data)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not get the token by password for user: %s, tenant: %s' % (username, tenant_id))
        return '', '', err

    ret = res.json()
    return ret['access_token'], ret['refresh_token'], ''

# client_credential 获取access_token  常用
def get_token_by_client_credential(client_id, client_secret):
    """

    :param client_id: 客户端id
    :param client_secret: 客户端密码
    :return: 返回access_token, refresh_token 以及error, access_token用于访问接口的令牌, refresh_token
    用于刷新获取新的access_token, error为返回的错误信息
    """
    data = {
        'grant_type': 'client_credential',
        'client_id': client_id,
        'client_secret': client_secret,
    }
    logger.info(data)

    path = '%s/uaa/v1/auth/tokens' % constant.WACLOUD_API_ENDPOINT
    res = requests.post(path, json=data)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not get the token by password for client_id: %s' % (client_id,))
        return '', '', err

    ret = res.json()
    return ret['access_token'], ret['refresh_token'], ''

# 刷新token方式获取access_token
def refresh_token(rtoken, tenant_id):
    """

    :return: 返回access_token, refresh_token 以及error, access_token用于访问接口的令牌, refresh_token
    用于刷新获取新的access_token, error为返回的错误信息
    """
    data = {
        'grant_type': 'refresh_token',
        'refresh_token': rtoken,
        'scope': 'global_access:tenant_admin,tenant:%s' % tenant_id,
    }

    path = '%s/uaa/v1/auth/tokens' % constant.WACLOUD_API_ENDPOINT
    res = requests.post(path, json=data)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not get the token by refresh token for tenant: %s' % (tenant_id,))
        return '', '', err

    ret = res.json()
    return ret['access_token'], ret['refresh_token'], ''

# 有问题 批量更新社保公积金待办任务
def update_si_tasks(ctx, tasks):
    """

    :param ctx: 访问接口需要的ctx
    :param tasks: 多个需要更新的任务
    :return: 是否成功和返回的status code
    """
    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
    if tasks is None or not isinstance(tasks, (list, )):
        return False, ''
    if len(tasks):
        return True, ''

    data = {
        'items': tasks,
    }

    path = '%s/bot/v1/si/tasks/op/batch-update' % (constant.WACLOUD_API_ENDPOINT, )
    res = requests.post(path, json=data, headers=headers)

    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.post(path, json=data, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not update the tasks')
        return False, res.status_code

    return True, res.status_code

# 更新社保公积金待办任务
def update_si_task(ctx, task_id, status, comment, hhr_type='', result=None, put_record=''):
    """

    :param access_token: 访问接口需要的access_token
    :param status: task需要更新的状态
    :param comment: task执行完的备注
    :param task_id: workai cloud平台的task id
    :return: 是否成功和返回的status code
    """
    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
    data = {
        'status': status,
        'comment': comment,
    }
    # 社保转入所需字段
    if hhr_type != '':
        data['hhr_type'] = hhr_type
    if put_record != '':
        data['put_record'] = put_record
    # 针对福州地区返回对应的险种结果和附件信息
    if result is not None:
        if 'files' in result.keys():
            att_key = '用工核定表'
            files = result['files']
            if att_key in files.keys():
                att_str = json.dumps(files[att_key])
                result['files'][att_key] = att_str

        data['result'] = result

    logger.info(str(data))
    path = '%s/bot/v1/si/tasks/%s' % (constant.WACLOUD_API_ENDPOINT, task_id)
    res = requests.put(path, json=data, headers=headers)

    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.put(path, json=data, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('The errors response is %s' %(res))
        logger.error('Could not update the task %s' % task_id)
        return False, res.status_code

    logger.info('task_id: %s update success' % task_id)
    return True, res.status_code

# 获取 Excel 一条数据的 详情
def get_si_task(ctx, task_id):
    """
    # 更新社保公积金待办任务
    :param ctx: 访问接口需要的上下文
    :param status: task需要更新的状态
    :param comment: task执行完的备注
    :param task_id: workai cloud平台的task id
    :return: task详情和返回的status code
    """
    # {'access_token' 'refresh_token' 'tenant_id'} client_id
    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}

    path = '%s/bot/v1/si/tasks/%s/detail' % (constant.WACLOUD_API_ENDPOINT, task_id)
    res = requests.get(path, headers=headers)

    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.get(path, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not get the task %s' % task_id)
        return None, res.status_code

    return res.json(), res.status_code

# 获取社保未办理完的任务       获取 上传sass平台的 Excel文件
def list_si_task(ctx, account, account_type, op_type, status, offset, limit, op_month, put_record_bot=True, op_progress=1):
    """

    :param access_token: 访问接口需要的access_token
    :param account: 账号
    :param account_type: 账号类型
    :param status: 状态
    :param limit: 分页每页最大数量
    :param offset: 分页偏移量
    :param op_progress: 前道数据状态 1:待办理  0：前道未确认
    :return: 返回task列表
    """
    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}

    queries = []
    if account != '':
        queries.append('account={account}'.format(account=account))
    if account_type != '':
        queries.append('account_type={account_type}'.format(account_type=account_type))
    if op_type != '':
        queries.append('op_type={op_type}'.format(op_type=op_type))
    if status != '':
        queries.append('status={status}'.format(status=status))
    if op_progress != '':
        queries.append('op_progress={op_progress}'.format(op_progress=op_progress))
    if op_month == '':
        timeNow = datetime.datetime.now().strftime('%Y%m')
        timeArray = time.strptime(timeNow, "%Y%m")
        timeStamp = int(time.mktime(timeArray))
        queries.append('op_month={op_month}'.format(op_month=timeStamp))
    else:
        timeArray = time.strptime(op_month, "%Y%m")
        timeStamp = int(time.mktime(timeArray))
        queries.append('op_month={}'.format(timeStamp))
    if put_record_bot:
        queries.append('put_record_bot={put_record_bot}'.format(put_record_bot=put_record_bot))

    # 处理接口数据分页参数
    if limit >= 1:
        queries.append("limit={limit}".format(limit=limit))
    if offset >= 0:
        queries.append('offset={offset}'.format(offset=offset))
    print(op_month)
    path = '%s/bot/v1/si/tasks' % (constant.WACLOUD_API_ENDPOINT, )
    if len(queries) > 0:
        path = path + '?{query}'.format(query='&'.join(queries))
    print(path)
    res = requests.get(path, headers=headers)
    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.get(path, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could Not Get List Task: %s' % (err,))
        return None, res.status_code
    return res.json(), res.status_code

# 获取社保 未办理完的 job
def list_si_job(ctx, conds, limit, offset):
    """

    :param access_token: 访问接口需要的access_token
    :param conds: 过滤条件
    :param limit: 分页每页最大数量
    :param offset: 分页偏移量
    :return: 返回job列表
    """
    # ctx = {'access_token': access_token, 'refresh_token': refresh_token, "tenant_id": get_cfg().client_id}
    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}

    path = '%s/bot/v1/si/jobs' % (constant.WACLOUD_API_ENDPOINT, )
    # conds = {'status': STATUS_UNCOMPLETED}
    if conds is not None and isinstance(conds, (dict, )) and len(conds) > 0:
        conds['limit'] = limit
        conds['offset'] = offset
        queries = []
        for k, v in conds.items():
            queries.append('%s=%s' % (k, v))
        if len(queries) > 0:
            path = '{}?{}'.format(path, '&'.join(queries))

    res = requests.get(path, headers=headers)
    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.get(path, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not list job')
        return None, res.status_code

    return res.json(), res.status_code

# 获取云平台对象文件
def download_file(ctx, file_object):
    """

    :return:
    """

    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    url = '{api_endpint}/filemeta/v1/object-redirect?'.format(api_endpint=constant.WACLOUD_API_ENDPOINT)

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}

    params = {'bucket': file_object['bucket'], 'object': file_object['path']}
    res = requests.get(url=url, params=params, headers=headers)

    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.get(url=url, params=params, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not get the download file {}'.format(file_object['path']))
        return '', res.status_code

    # 处理并下载人员头像图片文件逻辑
    local_file_dir = os.getcwd() + '\\files'
    if not os.path.isdir(local_file_dir):
        os.mkdir(local_file_dir)
    local_file_path = local_file_dir + "\\" + str(uuid.uuid1()) + ".jpg"
    request.urlretrieve(res.json()['download_url'], local_file_path)
    return local_file_path, 200

# 获取社保账号列表
def list_si_account(ctx, policy_category, account):
    """

    :param policy_category: 政策类型
    :param account: 账号
    :return: 返回account列表
    """
    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    if policy_category == '' or account == '':
        return None, 400

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}

    path = '%s/bot/v1/si/accounts?policy_category=%s&account=%s' % (constant.WACLOUD_API_ENDPOINT, policy_category, account)

    res = requests.get(path, headers=headers)

    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.get(path, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not list job')
        return None, res.status_code

    return res.json(), res.status_code

#
def upload(ctx, local_path):
    """上传附件"""
    object_path = ""
    if ctx is None or local_path is None:
        return 401, object_path

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
    data = {"object_type": "psiorder", "access_type": "sdk"}  # psiorder / insfile
    path = '%s/filemeta/v1/inits' % (constant.WACLOUD_API_ENDPOINT,)

    res = requests.post(path, json=data, headers=headers)
    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return 401, object_path
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.post(path, json=data, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        return res.status_code, object_path

    datas = res.json()
    # 使用临时token中的认证信息初始化StsAuth实例。
    auth = oss2.StsAuth(datas['access_key_id'], datas['access_key_secret'], datas['security_token'])
    # 使用StsAuth实例初始化存储空间。
    bucket = oss2.Bucket(auth, datas['domain'], datas['bucket'])
    object_path = datas['object_path']
    result = bucket.put_object_from_file(object_path, local_path)
    if os.path.exists(local_path):
        os.remove(local_path)
    return result.status, object_path

# 获取 员工管理 信息
def personnel_info(ctx,card_id):

    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}

    path = '%s/empmgm/v1/employees?status=in-service&keysearch=%s' % (constant.WACLOUD_API_ENDPOINT, card_id)
    res = requests.get(path, headers=headers)

    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.get(path, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not get the task %s' % card_id)
        return None, res.status_code

    return res.json(), res.status_code

# 员工详情 信息
def personnel_detail_info(ctx,personnel_id):

    if 'access_token' not in ctx or 'refresh_token' not in ctx or 'tenant_id' not in ctx:
        return None, 401

    headers = {'Authorization': 'Bearer %s' % ctx['access_token']}

    path = '%s/empmgm/v1/employees/personnel_id=%s' % (constant.WACLOUD_API_ENDPOINT, personnel_id)
    res = requests.get(path, headers=headers)

    if res.status_code == 401:
        access_token, _refresh_token, err = refresh_token(ctx['refresh_token'], ctx['tenant_id'])
        if err != '':
            return None, 401
        ctx['access_token'] = access_token
        ctx['refresh_token'] = _refresh_token
        headers = {'Authorization': 'Bearer %s' % ctx['access_token']}
        res = requests.get(path, headers=headers)

    err = handle_error(res, 200)
    if err != '':
        logger.error('Could not get the task %s' % personnel_id)
        return None, res.status_code

    return res.json(), res.status_code